package com.ubi.core.utils;

import com.ubi.core.http.HttpConnectionManager;
import org.apache.commons.lang3.StringUtils;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.NameValuePair;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.HttpClient;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.utils.URIUtils;
import org.apache.http.client.utils.URLEncodedUtils;
import org.apache.http.entity.StringEntity;
import org.apache.http.message.BasicHeader;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.protocol.HTTP;
import org.apache.http.util.EntityUtils;

import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.URI;
import java.net.URISyntaxException;
import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

import static org.apache.http.entity.ContentType.APPLICATION_XML;

/**
 * 标题、简要说明. <br> 类详细说明.
 * <p/>
 * Copyright: Copyright (c) 2015年10月2日 下午12:21:37
 * <p/>
 * Company: 网龙公司
 * <p/>
 *
 * @author Shunqin.Chen
 * @version 1.0.0
 */
public class HttpUtils {

    private static final String APPLICATION_JSON = "application/json";

    public static final String APPLICATION_X_WWW_FORM_URLENCODED = "application/x-www-form-urlencoded";

    private static final String CONTENT_TYPE_TEXT_JSON = "text/json";

    /**
     * 发送 post请求访问本地应用并根据传递参数不同返回不同结果
     */
    public static String postJson(String protocol, String domain, String path, String requestJson, Map<String, String> param) {
        // 创建默认的httpClient实例.
        HttpClient httpclient = HttpConnectionManager.getHttpClient();

        URI uri = buildUriByParam(protocol, domain, path, param);

        // 创建httppost
        HttpPost httppost = new HttpPost(uri);
        httppost.addHeader(HTTP.CONTENT_TYPE, APPLICATION_JSON);

        StringEntity se = null;
        HttpResponse response = null;
        String result = null;
        try {
            System.out.println("post json request:" + requestJson);
            se = new StringEntity(requestJson, HTTP.UTF_8);
            se.setContentType(CONTENT_TYPE_TEXT_JSON);
            se.setContentEncoding(new BasicHeader(HTTP.CONTENT_TYPE, APPLICATION_JSON));

            httppost.setEntity(se);
            response = httpclient.execute(httppost);

            HttpEntity entity = response.getEntity();
            if (entity != null) {
                result = EntityUtils.toString(entity, "UTF-8");
                printResponse(result);
            }
        } catch (UnsupportedEncodingException e2) {
            e2.printStackTrace();
        } catch (ClientProtocolException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }

        return result;
    }


    /**
     * @param url
     * @param param 例子：appid=123&mch_id=198912408
     * @return
     */
    public static String postXML(String url, String param) {
        // 创建默认的httpClient实例.
        HttpClient httpclient = HttpConnectionManager.getHttpClient();

        URI uri = null;
        try {
            uri = new URI(url);
            System.out.println("post form uri:" + uri.getRawPath());
        } catch (URISyntaxException e) {
            e.printStackTrace();
        }


        // 创建httppost
        HttpPost httppost = new HttpPost(uri);
        httppost.addHeader(HTTP.CONTENT_TYPE, APPLICATION_XML.getMimeType());

        StringEntity entity = null;

        HttpResponse response = null;
        String result = null;

        try {
            entity = new StringEntity(param, HTTP.UTF_8);
            entity.setContentType(APPLICATION_XML.getMimeType());
            entity.setContentEncoding(new BasicHeader(HTTP.CONTENT_TYPE, APPLICATION_XML.getMimeType()));
            httppost.setEntity(entity);
            response = httpclient.execute(httppost);

            HttpEntity resultEntity = response.getEntity();
            if (entity != null) {
                result = EntityUtils.toString(resultEntity, "UTF-8");
                printResponse(result);
            }
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        } catch (ClientProtocolException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return result;
    }

    public static String postForm(String url, Map<String, String> param) {
        // 创建默认的httpClient实例.
        HttpClient httpclient = HttpConnectionManager.getHttpClient();

        URI uri = null;
        try {
            uri = new URI(url);
            System.out.println("post form uri:" + uri.getRawPath());
        } catch (URISyntaxException e) {
            e.printStackTrace();
        }

        List<NameValuePair> qparams = buildValueParis(param);

        // 创建httppost
        HttpPost httppost = new HttpPost(uri);
        httppost.addHeader(HTTP.CONTENT_TYPE, APPLICATION_X_WWW_FORM_URLENCODED);

        UrlEncodedFormEntity entity = null;
        HttpResponse response = null;
        String result = null;

        try {
            entity = new UrlEncodedFormEntity(qparams, HTTP.UTF_8);
            entity.setContentType(APPLICATION_X_WWW_FORM_URLENCODED);
            entity.setContentEncoding(new BasicHeader(HTTP.CONTENT_TYPE, APPLICATION_X_WWW_FORM_URLENCODED));
            httppost.setEntity(entity);
            response = httpclient.execute(httppost);

            HttpEntity resultEntity = response.getEntity();
            if (entity != null) {
                result = EntityUtils.toString(resultEntity, "UTF-8");
                printResponse(result);
            }
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        } catch (ClientProtocolException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return result;
    }

    protected static void printResponse(String reponse) {
        System.out.println("--------------------------------------");
        System.out.println("Response content: " + reponse);
        System.out.println("--------------------------------------");
    }

    public static String httpGet(Map<String, String> param, String domain, String path) {
        return get(param, "http", domain, path);
    }

    public static String httpsGet(Map<String, String> param, String domain, String path) {
        return get(param, "https", domain, path);
    }

    public static String httpsGet(Map<String, String> param, Map<String, String> headerMap, String domain, String path) {
        return get(param, headerMap, "https", domain, path);
    }

    /**
     * 发送 get请求
     */
    public static String get(Map<String, String> param, String protocol, String domain, String path) {
        // 创建httpget.
        HttpGet httpGet = buildHttpGet(param, protocol, domain, path);

        System.out.println("executing request " + httpGet.getURI());
        return executeGet(httpGet);
    }

    /**
     * 发送 get请求
     */
    public static String get(Map<String, String> param, Map<String, String> headerMap, String protocol, String domain, String path) {
        // 创建httpget.
        HttpGet httpGet = buildHttpGet(param, headerMap, protocol, domain, path);
        System.out.println("executing request " + httpGet.getURI());
        return executeGet(httpGet);
    }

    private static String executeGet(HttpGet httpGet) {
        HttpClient httpclient = HttpConnectionManager.getHttpClient();
        // 执行get请求.
        HttpResponse response;
        String result = null;
        try {
            response = httpclient.execute(httpGet);
            // 获取响应实体
            HttpEntity entity = response.getEntity();
            System.out.println("--------------------------------------");
            // 打印响应状态
            System.out.println(response.getStatusLine());
            if (entity != null) {
                result = EntityUtils.toString(entity, "UTF-8");
                // 打印响应内容长度
                System.out.println("Response content length: " + entity.getContentLength());
                // 打印响应内容
                System.out.println("Response content: " + result);
            }
            System.out.println("------------------------------------");
        } catch (ClientProtocolException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return result;
    }

    /**
     * 发送 get请求
     */
    private static HttpGet buildHttpGet(Map<String, String> param, String protocol, String domain, String path) {
        return buildHttpGet(param, null, protocol, domain, path);
    }

    /**
     * 发送 get请求
     */
    private static HttpGet buildHttpGet(Map<String, String> param, Map<String, String> headerMap, String protocol, String domain, String path) {
        URI uri = buildUriByParam(protocol, domain, path, param);

        // 创建httpget.
        HttpGet httpget = new HttpGet(uri);
        if (headerMap == null) {
            return httpget;
        }

        for (Map.Entry<String, String> entry : headerMap.entrySet()) {
            httpget.setHeader(entry.getKey(), entry.getValue());
        }

        return httpget;
    }

    public static URI buildUriByParam(String protocol, String domain, String path, Map<String, String> param) {
        // build request param
        List<NameValuePair> qparams = buildValueParis(param);

        URI uri = null;
        try {
            uri = URIUtils.createURI(protocol, domain, -1, "/" + path, URLEncodedUtils.format(qparams, "UTF-8"), null);
        } catch (URISyntaxException e) {
            e.printStackTrace();
        }
        return uri;
    }

    public static List<NameValuePair> buildValueParis(Map<String, String> param) {
        List<NameValuePair> qparams = new ArrayList<>();
        if (param != null) {
            for (Map.Entry<String, String> entry : param.entrySet()) {
                qparams.add(new BasicNameValuePair(entry.getKey(), entry.getValue()));
            }
        }
        return qparams;
    }

    public static List<NameValuePair> buildValueParis(String param) {
        List<NameValuePair> qparams = new ArrayList<>();
        if (StringUtils.isBlank(param)) {
            return qparams;
        }

        return URLEncodedUtils.parse(param, Charset.forName("utf-8"));
    }

}
